package cn.com.demo.util;

import javax.crypto.KeyGenerator;
import javax.crypto.SecretKey;
import java.security.*;

public class Utils {

    private static String digits = "0123456789abcdef";

    public static String makeBlankString(int len) {
        char[] buf = new char[len];
        for (int i = 0; i < len; i++) {
            buf[i] = ' ';
        }
        return new String(buf);
    }

    /**
     * Return length many bytes of the passed in byte array as a hex string.
     *
     * @param data   the bytes to be converted.
     * @param length the number of bytes in the data block to be converted.
     * @return a hex representation of length bytes of data.
     */
    public static String toHex(byte[] data, int length) {
        StringBuffer buf = new StringBuffer();

        for (int i = 0; i != length; i++) {
            int v = data[i] & 0xff;

            buf.append(digits.charAt(v >> 4));
            buf.append(digits.charAt(v & 0xf));
        }

        return buf.toString();
    }

    /**
     * Return the passed in byte array as a hex string.
     *
     * @param data the bytes to be converted.
     * @return a hex representation of data.
     */
    public static String toHex(byte[] data) {
        return toHex(data, data.length);
    }

    public static String toString(byte[] bytes, int length) {
        char[] chars = new char[length];
        for (int i = 0; i < chars.length; i++) {
            chars[i] = (char) (bytes[i] & 0xff);
        }
        return new String(chars);
    }

    public static String toString(byte[] bytes) {
        return toString(bytes, bytes.length);
    }

    public static KeyPair generateRSAKeyPair(int length) throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "BC");
        kpGenerator.initialize(length, new SecureRandom());
        return kpGenerator.generateKeyPair();
    }

    public static KeyPair generateRSAKeyPair(int length, SecureRandom random) throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyPairGenerator kpGenerator = KeyPairGenerator.getInstance("RSA", "BC");
        kpGenerator.initialize(length, random);
        return kpGenerator.generateKeyPair();
    }


    private static class FixedRand extends SecureRandom {
        private static final long serialVersionUID = 1980357172957041134L;

        MessageDigest sha;
        byte[] state;

        public FixedRand() {
            try {
                this.sha = MessageDigest.getInstance("SHA-1", "BC");
                this.state = sha.digest();
            } catch (NoSuchAlgorithmException e) {
                e.printStackTrace();
            } catch (NoSuchProviderException e) {
                e.printStackTrace();
            }
        }

        public void nextBytes(byte[] bytes) {
            int off = 0;
            sha.update(state);
            while (off < bytes.length) {
                state = sha.digest();
                if (bytes.length - off > state.length) {
                    System.arraycopy(state, 0, bytes, off, state.length);
                } else {
                    System.arraycopy(state, 0, bytes, off, bytes.length - off);
                }
                off += state.length;
                sha.update(state);
            }
        }
    }

    /**
     * Return a SecureRandom which produces the same value.
     * <b>This is for testing only!</b>
     *
     * @return a fixed random
     */
    public static SecureRandom createFixedRandom() {
        return new FixedRand();
    }

    /**
     * @param keysize
     * @param random
     * @return en AES key
     * @throws NoSuchAlgorithmException
     * @throws NoSuchProviderException
     */
    public static SecretKey generateKeyForAES(int keysize, SecureRandom random)
            throws NoSuchAlgorithmException, NoSuchProviderException {
        KeyGenerator keyGen = KeyGenerator.getInstance("AES", "BC");
        keyGen.init(keysize, random);
        return keyGen.generateKey();
    }
}
